// ignore: implementation_imports, import_of_legacy_library_into_null_safe
import 'package:build/src/builder/build_step.dart';
import 'package:analyzer/dart/element/element.dart' as ele;

// ignore: import_of_legacy_library_into_null_safe
import 'package:source_gen/source_gen.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:build/build.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:dart_style/dart_style.dart';
import 'dart:io';
import 'formatter.dart';

class FormatterGenerator extends GeneratorForAnnotation<GFormatter> {
  final separator = Platform.pathSeparator;
  List<String> files = [];
  List result = [];
  List ignores = [
    '.entity.dart',
    '.route.dart',
    '.assets.dart',
    '.api.dart',
    '.iconfont.dart',
    '.interface.dart',
    '.formatter.dart',
    '.color.dart',
    '.size.dart',
  ];

  void queryFiles(String root, List<String> list) {
    try {
      var directory = Directory(root);
      List<FileSystemEntity> files = directory.listSync();
      files.forEach((f) {
        var bool = FileSystemEntity.isFileSync(f.path);
        if (!bool) {
          queryFiles(f.path, list);
        } else {
          ///之后可以通过文件hash 来判断文件是否被变化，格式化代码效率
          ///忽略自动生成代码
          var ignoreItem;
          try {
            ignoreItem =
                ignores.firstWhere((element) => f.path.endsWith(element));
          } catch (e) {}
          if (ignoreItem == null && f.path.endsWith('.dart')) {
            list.add(f.path);
          }
        }
      });
    } catch (e) {
      stdout.writeln("目录不存在！$root");
    }
  }

  String? formatCode(codeStr) {
    var formatter = DartFormatter();
    String? codeF;
    try {
      codeF = formatter.format(codeStr);
    } on FormatterException catch (ex) {
      stdout.writeln(ex);
    }
    return codeF;
  }

  formatFile(path) async {
    int lines;

    ///使用同一个file操作
    File file = File(path);
    try {
      ///先格式化代码
      String codeStr = await file.readAsString();
      String? codeF = formatCode(codeStr);
      if (codeF == null) {
        return null;
      }

      ///写入文件
      file = await file.writeAsString(codeF);

      ///再统计代码行数
      List<String> linesCode = await file.readAsLines();
      lines = linesCode.length;
      result.add({'path': path, 'lines': lines});
    } catch (e) {
      stdout.writeln('读取文件失败! $path $e');
    }
  }

  void printResult(int maxLine) {
    int lengthW = 80;
    StringBuffer sb = StringBuffer();
    for (int i = 0; i < lengthW; i++) {
      if (i == 0) sb.write('╔');
      sb.write('═');
    }
    sb.write('\n║ 需优化代码行数的文件如下: [line >= $maxLine]');
    int index = 0;
    result.forEach((item) {
      var lines = item['lines'];
      if (lines >= maxLine) {
        index++;
        sb.write('\n║ [$index]\t[line:$lines]\t${item['path']}\t');
      }
    });
    for (int i = 0; i < lengthW; i++) {
      if (i == 0) sb.write('\n╚');
      sb.write('═');
    }
    if (index > 0) {
      stdout.writeln(sb.toString());
    }
  }

  @override
  generateForAnnotatedElement(ele.Element element, ConstantReader annotation,
      BuildStep buildStep) async {
    int maxLine = 0;
    var enable = false;
    try {
      enable = annotation.read('enable').boolValue;
    } catch (e) {}
    if (!enable) return null;
    try {
      maxLine = annotation.read('maxLine').intValue;
    } catch (e) {}

    queryFiles('${Directory.current.path}${separator}lib', files);
    await Future.wait(
        files.map((path) async => await formatFile(path)).toList());

    if (result.length > 0) {
      printResult(maxLine);
    }
    return null;
  }
}

Builder formatterBuilder(BuilderOptions options) =>
    LibraryBuilder(FormatterGenerator(), generatedExtension: ".formatter.dart");
